<?php

namespace co2_OS;

function install($app,$version)

{
	if(!is_dir($sources=main::getSysVar('sources').'/'.$app.'-'.$version))
	throw new \co2\Exception('could not find app sources '.$sources);

	if(!file_exists($installer=$sources.'/install.php'))
	throw new \co2\Exception('could not find app installer');

	require_once $installer;

	$Version='v'.preg_replace('/\./','/v',$version);

	try
	{
		main::getAppsManifest()->$app=$version;
		
		is_int(file_put_contents(main::getSysVar('apps-manifest'),json_encode(main::getAppsManifest())))	?: \co2\Exception('could not update apps manifest');

		new \co2\bash\mkdir($app_base=main::getSysVar('apps').'/'.$app);

		new \co2\bash\mkdir("$app_base/$Version",(object)array('parent'=>true));

		$files=scandir($sources);

		foreach($files as $f)
		if($f!='.'&&$f!='..'&&$f!='install.php')
		copy("$sources/$f","$app_base/$Version/$f");
		
		if(is_null($manifest=json_decode(file_get_contents($sources.'/manifest'))))
		throw new \co2\Exception('could not read app manifest');
		
		if(isset($manifest->create_public_bucket) && $manifest->create_public_bucket===true)
		new \co2\bash\mkdir(main::getSysVar('bucket-apps').'/'.$app);
		
		if(isset($manifest->create_sqlite_database))
		new \co2\SQLite\db(main::getSysVar('sqlite').'/'.$manifest->create_sqlite_database.'.'.main::getSysVar('sqlite-ext'));

		$installer="\\co2_OS\\apps\\$app\\".preg_replace('%/%','\\',$Version).'\install';

		new $installer;
	}
	catch(\co2\Exception $e)
	{
		try
		{
			uninstall($app);
		}
		catch(\co2\Exception $e2)
		
		{
			throw new \co2\Exception('failed to install app '.$app.' v'.$version.' because "'.$e->getMessage().'". Additionnally, rolling back failed with error "'.$e2->getMessage().'" on '.$e2->getFile().':'.$e2->getLine().'. Try to run `co2 uninstall '.$app.'` from terminal',$e->getDebug(),$e->getLevel(),$e->getFile(),$e->getLine());
		}

		throw new \co2\Exception('failed to install app '.$app.' v'.$version.': '.$e->getMessage(),$e->getDebug(),$e->getLevel(),$e->getFile(),$e->getLine(),$e->getContext());
	}
}
